package bigbeard.tools.net.client.impl;

import bigbeard.tools.net.api.DataArrivalCallback;
import bigbeard.tools.net.api.StateChangeCallback;
import bigbeard.tools.net.client.BaseClientImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.nio.charset.StandardCharsets;

/**
 * @author bigbeard
 */
public class WebsocketClientImpl extends BaseClientImpl {
    protected final Log logger = LogFactory.getLog(WebsocketClientImpl.class);
    private MyWebSocketClient myWebSocketClient;

    @Override
    public void connect(String host, int port, String other) throws Exception {
        logger.info("开始连接到" + host + ":" + port + other);
        myWebSocketClient = new MyWebSocketClient(new URI("ws://" + host + ":" + port + other));
        myWebSocketClient.dataArrivalCallback = super.dataArrivalCallback;
        myWebSocketClient.stateChangeCallback = stateChangeCallback;
        myWebSocketClient.connect();
        logger.info("结束连接到" + host + ":" + port + other);
    }

    @Override
    public void disconnect() {
        if (null != myWebSocketClient) {
            myWebSocketClient.close();
            myWebSocketClient = null;
        }
    }

    @Override
    public int send(byte[] data) throws Exception {
        checkClient();
        myWebSocketClient.send(data);
        return data.length;
    }


    @Override
    public void send(String msg) throws Exception {
        checkClient();
        myWebSocketClient.send(msg);
    }

    @Override
    protected String getClientKey() {
        return "WEBSOCKET_CLIENT";
    }

    private void checkClient() throws Exception {
        if (null == myWebSocketClient || !myWebSocketClient.isOpen()) {
            throw new Exception("未连接或者连接已断开");
        }
    }

    private static class MyWebSocketClient extends WebSocketClient {
        DataArrivalCallback dataArrivalCallback;
        StateChangeCallback stateChangeCallback;
        private final Log logger = LogFactory.getLog(MyWebSocketClient.class);

        private void notifyState(String key, int state, String info) {
            if (null != stateChangeCallback) {
                stateChangeCallback.notifyStateChange(key, state, info);
            }
        }

        public MyWebSocketClient(URI serverUri) {
            super(serverUri);
        }

        @Override
        public void onOpen(ServerHandshake handShakeData) {
            logger.info("连接服务器结果:" + handShakeData.getHttpStatus()
                    + "," + handShakeData.getHttpStatusMessage());
            notifyState("", StateChangeCallback.CLIENT_OPENED, handShakeData.getHttpStatusMessage());
        }

        @Override
        public void onMessage(String message) {
            logger.info("收到:" + message);
            if (null == dataArrivalCallback) {
                logger.warn("未配置回调,信息不对外通知");
                return;
            }
            dataArrivalCallback.callback("", message.getBytes(StandardCharsets.UTF_8));
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {
            logger.info("收到关闭:" + code + "," + reason + "," + remote);
            notifyState("", StateChangeCallback.CLIENT_CLOSE,
                    "remote code:" + code + ",reason:" + reason + ",远程:" + remote);
        }

        @Override
        public void onError(Exception ex) {
            logger.error(ex);
            notifyState("", StateChangeCallback.CLIENT_ERROR, ex.getMessage());
        }
    }
}
